package me.mouse.gokistats;

import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Sound;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;

import me.mouse.gokistats.config.Config;
import me.mouse.gokistats.config.Language;
import me.mouse.gokistats.event.MenuLoadTalentItemEvent;
import me.mouse.gokistats.event.MenuOpenEvent;
import me.mouse.gokistats.event.TalentLevelChangeEvent;
import me.mouse.gokistats.listener.GokiStatsListener;
import me.mouse.gokistats.listener.TalentListener;
import me.mouse.gokistats.talent.RegisterTalent;
import me.mouse.gokistats.talent.Talent;
import me.mouse.gokistats.talent.TalentConfig;
import me.mouse.gokistats.util.PlayerData;
import me.mouse.gokistats.util.SetExpFix;

public class GokiStats extends JavaPlugin {
	public static FileConfiguration config;
	private static GokiStats plugin;
	public static Economy economy = null;
	public static boolean loadEco = false;
	public static File file;

	private boolean setupEconomy() {
		RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager()
				.getRegistration(Economy.class);
		if (economyProvider != null) {
			economy = economyProvider.getProvider();
		}

		return economy != null;
	}

	@Override
	public void onEnable() {
		plugin = this;

		if (!new File(getDataFolder(), "player").exists()) {
			new File(getDataFolder(), "player").mkdir();
		}
		boolean b = setupEconomy();
		if (!b) {
			getLogger().info(ChatColor.RED + "缺少Vault！！！");
		}
		loadEco = b;

		saveDefaultConfig();
		saveDefault("language.yml", false);
		saveDefault("talent.yml", false);

		file = getDataFolder();
		config = getConfig();
		Language.load();
		Config.loadConfig();

		getServer().getPluginManager().registerEvents(new GokiStatsListener(), this);
		getServer().getPluginManager().registerEvents(new TalentListener(), this);

		if (TalentConfig.getBetterConfig())
			TalentConfig.load();
		else {
			RegisterTalent.registerTalent(new Talent[] { getHeal(), getSpeed(), getSword(), getArmor(), getBow(),
					getAxe(), getDeathGod(), getRubber(), getFire(), getFall() });
		}

		getLogger().info("GokiStats V0.2.3 成功加载！");
	}

	@Override
	public void onDisable() {
		getLogger().info("GokiStats V0.2.3 已经停止加载！");
	}

	@Override
	@SuppressWarnings("deprecation")
	public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
		if ((label.equalsIgnoreCase("gs")) || (label.equalsIgnoreCase("gokistats"))) {
			if ((sender instanceof Player)) {
				Player player = (Player) sender;
				if ((args.length == 0) || (args[0].equalsIgnoreCase("help"))) {
					if ((player.hasPermission("gokistats.help")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						for (String s : Language.help) {
							player.sendMessage(s.replaceAll("&", "§"));
						}
						return true;
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if (args[0].equalsIgnoreCase("open")) {
					if ((player.hasPermission("gokistats.open")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						if (args.length == 1) {
							openMenu(player, 1);
							return true;
						}
						int page = Integer.parseInt(args[1]);
						openMenu(player, page);
						return true;
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if (args[0].equalsIgnoreCase("tellraw")) {
					if ((player.hasPermission("gokistats.tellraw")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						openTellraw(player);
						return true;
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if ((args[0].equalsIgnoreCase("levelup")) && ((player.hasPermission("gokistats.levelup"))
						|| (player.hasPermission("gokistats.*")) || (player.isOp()))) {
					if (args.length < 2) {
						player.sendMessage(Language.perfix + Language.notNumber);
						return true;
					}
					int t = Integer.parseInt(args[1]);
					Talent talent = RegisterTalent.getTalent(t);
					addLevel(player, talent);
				}

				if (args[0].equalsIgnoreCase("set")) {
					if ((player.hasPermission("gokistats.set")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						if (args.length < 4) {
							player.sendMessage(Language.perfix + Language.notNumber);
							return true;
						}
						String n = args[1];
						int t = Integer.parseInt(args[2]);
						int tlevel = Integer.parseInt(args[3]);
						Talent talent = RegisterTalent.getTalent(t);
						Player p = Bukkit.getPlayer(n);
						setLevel(p, talent, tlevel);
						player.sendMessage(Language.changeLevel.replaceAll("%player", p.getName())
								.replaceAll("%talent", talent.getDisplayName())
								.replaceAll("%tlevel", String.valueOf(tlevel)));
						return true;
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if (args[0].equalsIgnoreCase("up")) {
					if ((player.hasPermission("gokistats.set")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						if (args.length < 3) {
							player.sendMessage(Language.perfix + Language.notNumber);
							return true;
						}
						String n = args[1];
						int t = Integer.parseInt(args[2]);
						int tlevel;
						if (args.length > 3)
							tlevel = Integer.parseInt(args[3]);
						else {
							tlevel = 1;
						}
						Talent talent = RegisterTalent.getTalent(t);
						Player p = Bukkit.getPlayer(n);
						setLevel(p, talent, getLevel(p, talent) + tlevel);
						player.sendMessage(Language.changeLevel.replaceAll("%player", p.getName())
								.replaceAll("%talent", talent.getDisplayName())
								.replaceAll("%tlevel", String.valueOf(getLevel(p, talent) + tlevel)));
						return true;
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if (args[0].equalsIgnoreCase("info")) {
					if ((player.hasPermission("gokistats.info")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						if (args.length == 1) {
							player.sendMessage(Language.info.replaceAll("%player", player.getName()));
							List<Talent> talent = RegisterTalent.getRegisterTalent();
							for (Talent t : talent) {
								int tlevel = getLevel(player, t);
								player.sendMessage(Language.infoTalent.replaceAll("%talent", t.getDisplayName())
										.replaceAll("%tlevel", String.valueOf(tlevel)));
							}
							int point = getPoint(player);
							player.sendMessage(Language.infoPoint.replaceAll("%point", String.valueOf(point)));
							player.sendMessage(Language.infoLine);
							return true;
						}
						String name = args[1];
						Player p = Bukkit.getPlayer(name);
						player.sendMessage(Language.info.replaceAll("%player", p.getName()));
						List<Talent> talent = RegisterTalent.getRegisterTalent();
						for (Talent t : talent) {
							int tlevel = getLevel(p, t);
							player.sendMessage(Language.setPoint.replaceAll("%talent", t.getDisplayName())
									.replaceAll("%tlevel", String.valueOf(tlevel)));
						}
						int point = getPoint(p);
						player.sendMessage(Language.infoPoint.replaceAll("%point", String.valueOf(point)));
						player.sendMessage(Language.infoLine);
						return true;
					}

					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if (args[0].equalsIgnoreCase("point")) {
					if ((player.hasPermission("gokistats.point")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						if (args[1].equalsIgnoreCase("give")) {
							if (args.length < 4) {
								player.sendMessage(Language.perfix + Language.notNumber);
								return true;
							}
							Player p = Bukkit.getPlayer(args[2]);
							int point = Integer.parseInt(args[3]);
							setPoint(p, getPoint(p) + point);
							player.sendMessage(
									Language.perfix + Language.givePoint.replaceAll("%player", player.getName())
											.replaceAll("%point", String.valueOf(point)));
							return true;
						}
						if (args[1].equalsIgnoreCase("set")) {
							if (args.length < 4) {
								player.sendMessage(Language.perfix + Language.notNumber);
								return true;
							}
							Player p = Bukkit.getPlayer(args[2]);
							int point = Integer.parseInt(args[3]);
							setPoint(p, point);
							player.sendMessage(
									Language.perfix + Language.setPoint.replaceAll("%player", player.getName())
											.replaceAll("%point", String.valueOf(point)));
							return true;
						}
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				if (args[0].equalsIgnoreCase("reload")) {
					if ((player.hasPermission("gokistats.reload")) || (player.hasPermission("gokistats.*"))
							|| (player.isOp())) {
						reload();
						player.sendMessage(Language.perfix + Language.reload);
						return true;
					}
					player.sendMessage(Language.perfix + Language.notPer);
					return true;
				}
				player.sendMessage(Language.perfix + Language.notCommand);
				return true;
			}
			if ((args.length == 0) || (args[0].equalsIgnoreCase("help"))) {
				for (String s : Language.help) {
					getLogger().info(s);
				}
				return true;
			}
			if (args[0].equalsIgnoreCase("set")) {
				if (args.length < 4) {
					getLogger().info(Language.perfix + Language.notNumber);
					return true;
				}
				String n = args[1];
				int t = Integer.parseInt(args[2]);
				int tlevel = Integer.parseInt(args[3]);
				Talent talent = RegisterTalent.getTalent(t);
				Player p = Bukkit.getPlayer(n);
				setLevel(p, talent, tlevel);
				getLogger().info(Language.changeLevel.replaceAll("%player", p.getName())
						.replaceAll("%talent", talent.getDisplayName()).replaceAll("%tlevel", String.valueOf(tlevel)));
				return true;
			}
			if (args[0].equalsIgnoreCase("info")) {
				if (args.length < 2) {
					getLogger().info(Language.perfix + Language.notNumber);
					return true;
				}
				String name = args[1];
				Player p = Bukkit.getPlayer(name);
				getLogger().info(Language.info.replaceAll("%player", p.getName()));
				List<Talent> talent = RegisterTalent.getRegisterTalent();
				for (Talent t : talent) {
					int tlevel = getLevel(p, t);
					getLogger().info(Language.infoTalent.replaceAll("%talent", t.getDisplayName()).replaceAll("%tlevel",
							String.valueOf(tlevel)));
				}
				int point = getPoint(p);
				getLogger().info(Language.infoPoint.replaceAll("%point", String.valueOf(point)));
				getLogger().info(Language.infoLine);
				return true;
			}
			if (args[0].equalsIgnoreCase("point")) {
				if (args[1].equalsIgnoreCase("give")) {
					if (args.length < 4) {
						getLogger().info(Language.perfix + Language.notNumber);
						return true;
					}
					Player p = Bukkit.getPlayer(args[2]);
					int point = Integer.parseInt(args[3]);
					setPoint(p, getPoint(p) - point);
					getLogger().info(Language.givePoint.replaceAll("%player", p.getName()).replaceAll("%point",
							String.valueOf(point)));
					return true;
				}
				if (args[1].equalsIgnoreCase("set")) {
					if (args.length < 4) {
						getLogger().info(Language.perfix + Language.notNumber);
						return true;
					}
					Player p = Bukkit.getPlayer(args[2]);
					int point = Integer.parseInt(args[3]);
					setPoint(p, point);
					getLogger().info(Language.setPoint.replaceAll("%player", p.getName()).replaceAll("%point",
							String.valueOf(point)));
					return true;
				}
			}
			if (args[0].equalsIgnoreCase("up")) {
				if (args.length < 3) {
					getLogger().info(Language.perfix + Language.notNumber);
					return true;
				}
				String n = args[1];
				int t = Integer.parseInt(args[2]);
				int tlevel;
				if (args.length > 3)
					tlevel = Integer.parseInt(args[3]);
				else {
					tlevel = 1;
				}
				Talent talent = RegisterTalent.getTalent(t);
				Player p = Bukkit.getPlayer(n);
				setLevel(p, talent, getLevel(p, talent) + tlevel);
				getLogger().info(Language.changeLevel.replaceAll("%player", p.getName())
						.replaceAll("%talent", talent.getDisplayName()).replaceAll("%tlevel", String.valueOf(tlevel)));
				return true;
			}
			if (args[0].equalsIgnoreCase("reload")) {
				reload();
				getLogger().info(Language.reload);
				return true;
			}
		}

		return true;
	}

	public static void loadEffect(Player player) {
		if (RegisterTalent.getTalent("heal") != null) {
			int healLevel = getLevel(player, getHeal());
			double heal = config.getDouble("talent.heal.heal", 4.0D);
			player.setMaxHealth(healLevel * heal + 20.0D);
			player.setHealth(healLevel * heal + 20.0D);
		}
		if (RegisterTalent.getTalent("speed") != null) {
			int speedLevel = getLevel(player, getSpeed());
			float speed = (float) config.getDouble("talent.speed.speed", 5.0D);
			player.setWalkSpeed(speed * speedLevel / 500.0F + 0.2F);
		}
	}

	public void reload() {
		config = load("config.yml");
		Config.loadConfig();
		Language.load();
		RegisterTalent.clearRegisterTalent();
		if (TalentConfig.getBetterConfig())
			TalentConfig.load();
		else
			RegisterTalent.registerTalent(new Talent[] { getHeal(), getSpeed(), getSword(), getArmor(), getBow(),
					getAxe(), getDeathGod(), getRubber(), getFire() });
	}

	public static Talent getHeal() {
		Talent talent = new Talent("heal", 0);
		talent.setDisplayName("顽强生命");
		talent.setMaxLevel(25);
		talent.setSlot(1);
		ItemStack Item = new ItemStack(Material.GOLDEN_APPLE);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "顽强生命 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "生命增加  %heal 颗心");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.heal.enable", true));
		return talent;
	}

	public static Talent getSpeed() {
		Talent talent = new Talent("speed", 1);
		talent.setDisplayName("潜行者");
		talent.setMaxLevel(25);
		talent.setSlot(3);
		ItemStack Item = new ItemStack(Material.IRON_BOOTS);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "潜行者 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "移动速度增加  %speed%");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.speed.enable", true));
		return talent;
	}

	public static Talent getSword() {
		Talent talent = new Talent("sword", 2);
		talent.setDisplayName("剑客");
		talent.setMaxLevel(25);
		talent.setSlot(5);
		ItemStack Item = new ItemStack(Material.DIAMOND_SWORD);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "剑客 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "增加  %sword% 的剑类攻击伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.sowrd.enable", true));
		return talent;
	}

	public static Talent getArmor() {
		Talent talent = new Talent("armor", 3);
		talent.setDisplayName("防御意识");
		talent.setMaxLevel(25);
		talent.setSlot(7);
		ItemStack Item = new ItemStack(Material.DIAMOND_CHESTPLATE);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "防御意识 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "减少  %armor% 的物理伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.armor.enable", true));
		return talent;
	}

	public static Talent getBow() {
		Talent talent = new Talent("bow", 4);
		talent.setDisplayName("游侠");
		talent.setMaxLevel(25);
		talent.setSlot(10);
		ItemStack Item = new ItemStack(Material.BOW);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "游侠 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "增加  %bow% 的弓箭伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.bow.enable", true));
		return talent;
	}

	public static Talent getAxe() {
		Talent talent = new Talent("axe", 5);
		talent.setDisplayName("斧术");
		talent.setMaxLevel(25);
		talent.setSlot(12);
		ItemStack Item = new ItemStack(Material.DIAMOND_AXE);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "斧术 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "增加  %axe% 的斧类武器伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.axe.enable", true));
		return talent;
	}

	public static Talent getDeathGod() {
		Talent talent = new Talent("deathgod", 6);
		talent.setDisplayName("死神附体");
		talent.setMaxLevel(25);
		talent.setSlot(14);
		ItemStack Item = new ItemStack(Material.GOLD_HOE);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "死神附体 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "有  %deathgod% 的几率直接击杀一个低于20血的生物");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.deathgod.enable", true));
		return talent;
	}

	public static Talent getRubber() {
		Talent talent = new Talent("rubber", 7);
		talent.setDisplayName("橡胶体质");
		talent.setMaxLevel(25);
		talent.setSlot(16);
		ItemStack Item = new ItemStack(Material.SLIME_BALL);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "橡胶体质 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "减少  %rubber% 的爆炸伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.rubber.enable", true));
		return talent;
	}

	public static Talent getFire() {
		Talent talent = new Talent("fire", 8);
		talent.setDisplayName("烈焰之魂");
		talent.setMaxLevel(25);
		talent.setSlot(19);
		ItemStack Item = new ItemStack(Material.FIRE);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "烈焰之魂 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "减少  %fire% 的灼烧伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.fire.enable", true));
		return talent;
	}

	public static Talent getFall() {
		Talent talent = new Talent("fall", 9);
		talent.setDisplayName("羽落");
		talent.setMaxLevel(25);
		talent.setSlot(21);
		ItemStack Item = new ItemStack(Material.FEATHER);
		ItemMeta MItem = Item.getItemMeta();
		MItem.setDisplayName(ChatColor.GOLD + "羽落 当前等级 %tlevel");
		List<String> ItemLore = new ArrayList<String>();
		ItemLore.add(ChatColor.WHITE + "减少  %fall% 的掉落伤害");
		ItemLore.add(ChatColor.AQUA + "下一级需要：%next %payment");
		ItemLore.add("%can");
		MItem.setLore(ItemLore);
		Item.setItemMeta(MItem);
		talent.setItem(Item);
		talent.setEnable(config.getBoolean("talent.fall.enable", true));
		return talent;
	}

	public static int getIntResult(String f, int l) {
		ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
		f = f.replaceAll("%level", String.valueOf(l));
		try {
			Object res = jse.eval(f);
			DecimalFormat dcmFmt = new DecimalFormat("###########");
			return Integer.parseInt(dcmFmt.format(res));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 2100000000;
	}

	public static double getResult(String f, int l) {
		ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript");
		f = f.replaceAll("%level", String.valueOf(l));
		try {
			Object res = jse.eval(f);
			return Double.parseDouble(res.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 2100000000.0D;
	}

	public static int getLevel(OfflinePlayer p, Talent t) {
		PlayerData data = new PlayerData(p);
		String name = t.getName();
		int level = data.getFileConfiguration().getInt(name, -1);
		if (level <= -1) {
			FileConfiguration config = data.getFileConfiguration();
			config.set(name, Integer.valueOf(0));
			data.setFileConfiguration(config);
			data.save();
			return 0;
		}
		return level;
	}

	public static boolean addLevel(OfflinePlayer p, Talent t) {
		int level = getLevel(p, t);
		TalentLevelChangeEvent e = new TalentLevelChangeEvent(p.getPlayer(), t, level,
				TalentLevelChangeEvent.ChangeType.UP_LEVEL);
		Bukkit.getServer().getPluginManager().callEvent(e);
		if (!e.isCancelled()) {
			PlayerData data = new PlayerData(p);
			String name = t.getName();
			double cost = getResult(t.getFormula(), level);
			boolean overCost = cost(p.getPlayer(), cost, t.getPayment());
			if (overCost) {
				FileConfiguration config = data.getFileConfiguration();
				config.set(name, Integer.valueOf(level + 1));
				data.setFileConfiguration(config);
				data.save();
				loadEffect(p.getPlayer());
				p.getPlayer().playSound(p.getPlayer().getLocation(), Sound.ANVIL_USE, 1.0F, 1.0F);
				return true;
			}
		}
		return false;
	}

	public static void setLevel(OfflinePlayer p, Talent t, int level) {
		TalentLevelChangeEvent e = new TalentLevelChangeEvent(p.getPlayer(), t, level,
				TalentLevelChangeEvent.ChangeType.COMMAND);
		Bukkit.getServer().getPluginManager().callEvent(e);
		if (!e.isCancelled()) {
			PlayerData data = new PlayerData(p);
			String name = t.getName();
			FileConfiguration config = data.getFileConfiguration();
			config.set(name, Integer.valueOf(level));
			data.setFileConfiguration(config);
			data.save();
			loadEffect(p.getPlayer());
		}
	}

	public static int getPoint(OfflinePlayer p) {
		PlayerData data = new PlayerData(p);
		int Point = data.getFileConfiguration().getInt("point", -1);
		if (Point <= -1) {
			FileConfiguration config = data.getFileConfiguration();
			config.set("point", Integer.valueOf(0));
			data.setFileConfiguration(config);
			data.save();
			return 0;
		}
		return Point;
	}

	public static void setPoint(OfflinePlayer p, int Point) {
		PlayerData data = new PlayerData(p);
		FileConfiguration config = data.getFileConfiguration();
		config.set("point", Integer.valueOf(Point));
		data.setFileConfiguration(config);
		data.save();
	}

	@SuppressWarnings("deprecation")
	public static void openMenu(final Player player, final int page) {
		if ((page <= 0) || (page > 9)) {
			return;
		}
		if (player == null) {
			return;
		}
		Inventory inv = Bukkit.createInventory(null, 54, "GokiStats-" + page);
		for (Talent t : RegisterTalent.getRegisterTalent()) {
			boolean b = true;
			if ((t.getSlot() > page * 54 - 1) || (t.getSlot() < page * 54 - 54)) {
				b = false;
			}
			if (b) {
				int Exp = player.getTotalExperience();
				int ExpLevel = player.getLevel();
				double Money = 0.0D;
				if (loadEco) {
					try {
						Money = economy.getBalance(player);
					} catch (NoSuchMethodError e) {
						Money = economy.getBalance(player.getName());
					}
				}
				int Point = getPoint(player);
				int Level = getLevel(player, t);
				int MaxLevel = t.getMaxLevel();
				int Slot = t.getSlot() - (page - 1) * 54;
				String formula = t.getFormula();
				double Next = getResult(formula, Level);
				String Can = getCan(player, Next, t, Level);
				String Payment = getPayment(t.getPayment());
				ItemStack Item = new ItemStack(t.getItem());
				ItemMeta Meta = Item.getItemMeta();
				String DisplayName = Meta.getDisplayName().replaceAll("&", "§")
						.replaceAll("%tlevel", String.valueOf(Level)).replaceAll("%next", String.valueOf(Next))
						.replaceAll("%player", player.getName()).replaceAll("%maxlevel", String.valueOf(MaxLevel))
						.replaceAll("%exp", String.valueOf(Exp)).replaceAll("%money", String.valueOf(Money))
						.replaceAll("%level", String.valueOf(ExpLevel)).replaceAll("%point", String.valueOf(Point))
						.replaceAll("%can", Can).replaceAll("%payment", Payment);
				Meta.setDisplayName(DisplayName);
				List<String> Lore = Meta.getLore();
				List<String> ItemLore = new ArrayList<String>();
				for (String s : Lore) {
					String str = s.replaceAll("&", "§").replaceAll("%tlevel", String.valueOf(Level))
							.replaceAll("%next", String.valueOf(Next)).replaceAll("%player", player.getName())
							.replaceAll("%maxlevel", String.valueOf(MaxLevel)).replaceAll("%exp", String.valueOf(Exp))
							.replaceAll("%money", String.valueOf(Money)).replaceAll("%level", String.valueOf(ExpLevel))
							.replaceAll("%point", String.valueOf(Point)).replaceAll("%can", Can)
							.replaceAll("%payment", Payment);
					ItemLore.add(str);
				}
				Meta.setLore(ItemLore);
				Item.setItemMeta(Meta);
				MenuLoadTalentItemEvent e = new MenuLoadTalentItemEvent(player, t, Item);
				Bukkit.getServer().getPluginManager().callEvent(e);
				if (!e.isCancelled()) {
					inv.setItem(Slot, e.getItem());
				}
			}
		}
		MenuOpenEvent e = new MenuOpenEvent(inv, player);
		Bukkit.getServer().getPluginManager().callEvent(e);
		if (!e.isCancelled()) {
			Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
				@Override
				public void run() {
					GokiStats.openMenu(player, page);
				}
			}, 1L);
		}
	}

	@SuppressWarnings("deprecation")
	public static void openTellraw(Player player) {
		if (player == null) {
			return;
		}
		for (Talent t : RegisterTalent.getRegisterTalent()) {
			int Exp = player.getTotalExperience();
			int ExpLevel = player.getLevel();
			double Money = 0.0D;
			if (loadEco) {
				try {
					Money = economy.getBalance(player);
				} catch (NoSuchMethodError e) {
					Money = economy.getBalance(player.getName());
				}
			}
			int Point = getPoint(player);
			int Level = getLevel(player, t);
			int MaxLevel = t.getMaxLevel();
			String formula = t.getFormula();
			double Next = getResult(formula, Level);
			String Can = getCan(player, Next, t, Level);
			String Payment = getPayment(t.getPayment());
			ItemStack Item = new ItemStack(t.getItem());
			ItemMeta Meta = Item.getItemMeta();
			String DisplayName = Meta.getDisplayName().replaceAll("&", "§").replaceAll("%tlevel", String.valueOf(Level))
					.replaceAll("%next", String.valueOf(Next)).replaceAll("%player", player.getName())
					.replaceAll("%maxlevel", String.valueOf(MaxLevel)).replaceAll("%exp", String.valueOf(Exp))
					.replaceAll("%money", String.valueOf(Money)).replaceAll("%level", String.valueOf(ExpLevel))
					.replaceAll("%point", String.valueOf(Point)).replaceAll("%can", Can)
					.replaceAll("%payment", Payment);
			Meta.setDisplayName(DisplayName);
			List<String> Lore = Meta.getLore();
			List<String> ItemLore = new ArrayList<String>();
			for (String s : Lore) {
				String str = s.replaceAll("&", "§").replaceAll("%tlevel", String.valueOf(Level))
						.replaceAll("%next", String.valueOf(Next)).replaceAll("%player", player.getName())
						.replaceAll("%maxlevel", String.valueOf(MaxLevel)).replaceAll("%exp", String.valueOf(Exp))
						.replaceAll("%money", String.valueOf(Money)).replaceAll("%level", String.valueOf(ExpLevel))
						.replaceAll("%point", String.valueOf(Point)).replaceAll("%can", Can)
						.replaceAll("%payment", Payment);
				ItemLore.add(str);
			}
			Meta.setLore(ItemLore);
			Item.setItemMeta(Meta);
			MenuLoadTalentItemEvent e = new MenuLoadTalentItemEvent(player, t, Item);
			Bukkit.getServer().getPluginManager().callEvent(e);
			if (!e.isCancelled()) {
				ItemStack item = e.getItem();
				String lore = item.getItemMeta().getLore().toString();
				lore = lore.replace(":", ";");
				String command = "tellraw " + player.getName() + " {\"text\":\"\",\"extra\":[{\"text\":\""
						+ t.getDisplayName() + ": \"},{\"text\":\"" + Language.tellrawTalentInfo
						+ "\",\"hoverEvent\":{\"action\":\"show_item\",\"value\":\"{id:" + item.getTypeId()
						+ ",tag:{display:{Name:\"" + item.getItemMeta().getDisplayName() + "\",Lore:\"" + lore
						+ "\"}}}\"}},{\"text\":\"" + Language.tellrawTalentInfo
						+ "\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/gs levelup " + t.getID()
						+ "\"}}]}";
				Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
				Bukkit.getLogger().info(command);
			}
		}
	}

	@SuppressWarnings("deprecation")
	private static String getCan(Player player, double cost, Talent talent, int Level) {
		int MaxLevel = talent.getMaxLevel();
		if (Level >= MaxLevel) {
			return Language.levelMax;
		}
		PaymentType type = talent.getPayment();
		switch (type) {
		case EXP:
			int exp = player.getTotalExperience();
			if (exp >= cost) {
				return Language.levelup;
			}
			return Language.notLevelup;
		case LEVEL:
			int level = player.getLevel();
			if (level >= cost) {
				return Language.levelup;
			}
			return Language.notLevelup;
		case MONEY:
			double money = economy.getBalance(Bukkit.getOfflinePlayer(player.getName()));
			if (money >= cost) {
				return Language.levelup;
			}
			return Language.notLevelup;
		case POINT:
			int point = getPoint(player);
			if (point >= cost) {
				return Language.levelup;
			}
			return Language.notLevelup;
		default:
			break;
		}

		return Language.notLevelup;
	}

	public static boolean cost(Player player, double cost, PaymentType type) {
		int icost = (int) cost;
		switch (type) {
		case EXP:
			int exp = SetExpFix.getTotalExperience(player);
			if (exp >= cost) {
				SetExpFix.setTotalExperience(player, exp - icost);
				return true;
			}
			return false;
		case LEVEL:
			int level = player.getLevel();
			int el = SetExpFix.getTotalExperience(player) - SetExpFix.getExpToLevel(level);
			if (level >= cost) {
				SetExpFix.setTotalExperience(player, SetExpFix.getExpToLevel(level - icost) + el);
				return true;
			}
			return false;
		case MONEY:
			return economy.withdrawPlayer(player, cost).transactionSuccess();
		case POINT:
			int point = getPoint(player);
			if (point >= cost) {
				setPoint(player, point - icost);
				return true;
			}
			return false;
		default:
			return false;
		}
	}

	public static String getPayment(PaymentType payment) {
		switch (payment) {
		case EXP:
			return Language.exp;
		case LEVEL:
			return Language.level;
		case MONEY:
			return Language.money;
		case POINT:
			return Language.point;
		case UNKNOWN:
			return Language.unknown;
		default:
			return "DIFAULT";
		}
	}

	public static PaymentType getPayment(int id) {
		switch (id) {
		case 0:
			return PaymentType.EXP;
		case 1:
			return PaymentType.LEVEL;
		case 2:
			return PaymentType.MONEY;
		case 3:
			return PaymentType.POINT;
		case 4:
			return PaymentType.UNKNOWN;
		case 5:
			return PaymentType.DIFAULT;
		}
		return PaymentType.DIFAULT;
	}

	private void saveDefault(String File, boolean b) {
		saveResource(File, b);
	}

	public static FileConfiguration load(String name) {
		File file = new File(GokiStats.file, name);
		if (!file.exists()) {
			if (!file.getParentFile().exists())
				file.getParentFile().mkdirs();
			try {
				file.createNewFile();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return YamlConfiguration.loadConfiguration(file);
	}

	public static enum PaymentType {
		EXP, LEVEL, MONEY, POINT, UNKNOWN, DIFAULT;
	}
}
